# ============================================================================
# Clang 编译器配置模块
# ============================================================================
# 提供 Linux 下 Clang 编译器的自动检测和配置
# Windows 上不考虑 Clang，使用 MSVC
# ============================================================================
# 注意：此文件必须在 project() 之前被 include，以便正确设置编译器
# ============================================================================

if(UNIX AND NOT WIN32)
    # 检查是否使用 Clang（Linux 上默认使用 Clang）
    # 优先级：CMake 变量 (-DUSE_CLANG) > 环境变量 (USE_CLANG) > 默认值
    # 可以通过以下方式控制（1=使用 Clang，0=使用 GCC）：
    #   1. cmake -DUSE_CLANG=0 ...
    #   2. export USE_CLANG=0 && cmake ...
    #   3. USE_CLANG=0 cmake ...
    if(DEFINED USE_CLANG)
        # 使用 CMake 变量（通过 -D 参数传递）
        set(USE_CLANG "${USE_CLANG}")
    elseif(DEFINED ENV{USE_CLANG})
        # 使用环境变量
        set(USE_CLANG "$ENV{USE_CLANG}")
    else()
        # Linux 上默认使用 Clang
        # 注意：使用 NOT APPLE 而不是 CMAKE_SYSTEM_NAME，因为某些 Linux 发行版
        # （如 CentOS）的 CMAKE_SYSTEM_NAME 可能不是 "Linux"
        # 在 UNIX AND NOT WIN32 的前提下，如果不是 APPLE，就应该是 Linux
        if(NOT APPLE)
            set(USE_CLANG "1")
        else()
            # macOS 上默认不使用 Clang（使用系统默认的 Clang/LLVM）
            set(USE_CLANG "0")
        endif()
    endif()
    
    # 调试信息：显示 USE_CLANG 的值
    message(STATUS "[ClangConfig] USE_CLANG = ${USE_CLANG}")
    
    # 如果使用 Clang
    if(USE_CLANG STREQUAL "1")
        # 获取 Clang 版本（默认 14）
        # 优先级：CMake 变量 > 环境变量 > 默认值
        if(DEFINED CLANG_VERSION)
            set(CLANG_VERSION "${CLANG_VERSION}")
        elseif(DEFINED ENV{CLANG_VERSION})
            set(CLANG_VERSION "$ENV{CLANG_VERSION}")
        else()
            set(CLANG_VERSION "14")
        endif()
        
        # 查找 Clang 编译器（优先级：版本化 -> 默认）
        find_program(CLANG_C_COMPILER 
            NAMES clang-${CLANG_VERSION} clang
            PATHS /usr/bin /usr/local/bin
            NO_DEFAULT_PATH
        )
        if(CLANG_C_COMPILER)
            find_program(CLANG_CXX_COMPILER 
                NAMES clang++-${CLANG_VERSION} clang++
                PATHS /usr/bin /usr/local/bin
                NO_DEFAULT_PATH
            )
        endif()
        
        # 🔥 关键：验证找到的编译器路径，确保不是 ccache 包装器
        if(CLANG_C_COMPILER)
            string(FIND "${CLANG_C_COMPILER}" "ccache" CCACHE_FOUND)
            if(NOT CCACHE_FOUND EQUAL -1)
                message(WARNING "⚠️  检测到 Clang 路径包含 ccache: ${CLANG_C_COMPILER}")
                message(WARNING "   正在查找真实编译器...")
                unset(CLANG_C_COMPILER)
                unset(CLANG_CXX_COMPILER)
            endif()
        endif()
        
        # 如果找到了 Clang，设置编译器（必须在 project() 之前）
        if(CLANG_C_COMPILER AND CLANG_CXX_COMPILER)
            # 使用 FORCE 确保即使缓存中已有其他编译器，也使用 Clang
            # 这对于 CLion 等 IDE 很重要，因为它们可能缓存了旧的编译器设置
            set(CMAKE_C_COMPILER "${CLANG_C_COMPILER}" CACHE FILEPATH "C compiler" FORCE)
            set(CMAKE_CXX_COMPILER "${CLANG_CXX_COMPILER}" CACHE FILEPATH "C++ compiler" FORCE)
            message(STATUS "✅ 已选择 Clang 编译器 (版本: ${CLANG_VERSION}) ⚡")
            message(STATUS "   C 编译器: ${CLANG_C_COMPILER}")
            message(STATUS "   C++ 编译器: ${CLANG_CXX_COMPILER}")
        else()
            message(WARNING "⚠️  未找到 Clang 编译器，将使用 GCC")
            message(WARNING "   提示: 安装 Clang: sudo apt-get install clang-${CLANG_VERSION}")
        endif()
    else()
        # USE_CLANG=0，显式查找并设置 GCC 编译器
        # 这确保即使 CMakeCache.txt 中缓存了 Clang，也会使用 GCC
        
        # 首先清除可能存在的 Clang 编译器缓存
        unset(CMAKE_C_COMPILER CACHE)
        unset(CMAKE_CXX_COMPILER CACHE)
        
        # 🔥 关键：查找 GCC 编译器，确保不使用 ccache 包装器
        # 优先级：环境变量 > 直接检查标准路径 > find_program
        set(GCC_C_COMPILER "")
        set(GCC_CXX_COMPILER "")
        
        # 方法0：优先检查环境变量
        # 优先级：CMAKE_C_COMPILER/CMAKE_CXX_COMPILER > CC/CXX > 其他查找方法
        # 允许用户通过环境变量指定编译器路径，例如 /usr/local/bin/g++
        
        # 检查 CMAKE_C_COMPILER（CMake 特定环境变量）
        if(DEFINED ENV{CMAKE_C_COMPILER})
            set(ENV_GCC_C_COMPILER "$ENV{CMAKE_C_COMPILER}")
            if(EXISTS "${ENV_GCC_C_COMPILER}")
                # 验证不是 ccache 包装器
                execute_process(
                    COMMAND readlink -f "${ENV_GCC_C_COMPILER}"
                    OUTPUT_VARIABLE REAL_ENV_GCC_PATH
                    OUTPUT_STRIP_TRAILING_WHITESPACE
                    ERROR_QUIET
                )
                if(REAL_ENV_GCC_PATH)
                    string(FIND "${REAL_ENV_GCC_PATH}" "ccache" CCACHE_FOUND)
                    if(CCACHE_FOUND EQUAL -1)
                        set(GCC_C_COMPILER "${ENV_GCC_C_COMPILER}")
                        message(STATUS "[ClangConfig] 从环境变量 CMAKE_C_COMPILER 获取 C 编译器: ${GCC_C_COMPILER}")
                    endif()
                else()
                    # 如果 readlink 失败，直接检查路径字符串
                    string(FIND "${ENV_GCC_C_COMPILER}" "ccache" CCACHE_FOUND)
                    if(CCACHE_FOUND EQUAL -1)
                        set(GCC_C_COMPILER "${ENV_GCC_C_COMPILER}")
                        message(STATUS "[ClangConfig] 从环境变量 CMAKE_C_COMPILER 获取 C 编译器: ${GCC_C_COMPILER}")
                    endif()
                endif()
            endif()
        endif()
        
        # 检查 CC（标准环境变量，如果 CMAKE_C_COMPILER 未设置）
        if(NOT GCC_C_COMPILER AND DEFINED ENV{CC})
            set(ENV_CC "$ENV{CC}")
            if(EXISTS "${ENV_CC}")
                # 验证不是 ccache 包装器
                execute_process(
                    COMMAND readlink -f "${ENV_CC}"
                    OUTPUT_VARIABLE REAL_ENV_CC_PATH
                    OUTPUT_STRIP_TRAILING_WHITESPACE
                    ERROR_QUIET
                )
                if(REAL_ENV_CC_PATH)
                    string(FIND "${REAL_ENV_CC_PATH}" "ccache" CCACHE_FOUND)
                    if(CCACHE_FOUND EQUAL -1)
                        set(GCC_C_COMPILER "${ENV_CC}")
                        message(STATUS "[ClangConfig] 从环境变量 CC 获取 C 编译器: ${GCC_C_COMPILER}")
                    endif()
                else()
                    # 如果 readlink 失败，直接检查路径字符串
                    string(FIND "${ENV_CC}" "ccache" CCACHE_FOUND)
                    if(CCACHE_FOUND EQUAL -1)
                        set(GCC_C_COMPILER "${ENV_CC}")
                        message(STATUS "[ClangConfig] 从环境变量 CC 获取 C 编译器: ${GCC_C_COMPILER}")
                    endif()
                endif()
            endif()
        endif()
        
        # 检查 CMAKE_CXX_COMPILER（CMake 特定环境变量）
        if(DEFINED ENV{CMAKE_CXX_COMPILER})
            set(ENV_GCC_CXX_COMPILER "$ENV{CMAKE_CXX_COMPILER}")
            if(EXISTS "${ENV_GCC_CXX_COMPILER}")
                # 验证不是 ccache 包装器
                execute_process(
                    COMMAND readlink -f "${ENV_GCC_CXX_COMPILER}"
                    OUTPUT_VARIABLE REAL_ENV_GXX_PATH
                    OUTPUT_STRIP_TRAILING_WHITESPACE
                    ERROR_QUIET
                )
                if(REAL_ENV_GXX_PATH)
                    string(FIND "${REAL_ENV_GXX_PATH}" "ccache" CCACHE_FOUND)
                    if(CCACHE_FOUND EQUAL -1)
                        set(GCC_CXX_COMPILER "${ENV_GCC_CXX_COMPILER}")
                        message(STATUS "[ClangConfig] 从环境变量 CMAKE_CXX_COMPILER 获取 C++ 编译器: ${GCC_CXX_COMPILER}")
                    endif()
                else()
                    # 如果 readlink 失败，直接检查路径字符串
                    string(FIND "${ENV_GCC_CXX_COMPILER}" "ccache" CCACHE_FOUND)
                    if(CCACHE_FOUND EQUAL -1)
                        set(GCC_CXX_COMPILER "${ENV_GCC_CXX_COMPILER}")
                        message(STATUS "[ClangConfig] 从环境变量 CMAKE_CXX_COMPILER 获取 C++ 编译器: ${GCC_CXX_COMPILER}")
                    endif()
                endif()
            endif()
        endif()
        
        # 检查 CXX（标准环境变量，如果 CMAKE_CXX_COMPILER 未设置）
        if(NOT GCC_CXX_COMPILER AND DEFINED ENV{CXX})
            set(ENV_CXX "$ENV{CXX}")
            if(EXISTS "${ENV_CXX}")
                # 验证不是 ccache 包装器
                execute_process(
                    COMMAND readlink -f "${ENV_CXX}"
                    OUTPUT_VARIABLE REAL_ENV_CXX_PATH
                    OUTPUT_STRIP_TRAILING_WHITESPACE
                    ERROR_QUIET
                )
                if(REAL_ENV_CXX_PATH)
                    string(FIND "${REAL_ENV_CXX_PATH}" "ccache" CCACHE_FOUND)
                    if(CCACHE_FOUND EQUAL -1)
                        set(GCC_CXX_COMPILER "${ENV_CXX}")
                        message(STATUS "[ClangConfig] 从环境变量 CXX 获取 C++ 编译器: ${GCC_CXX_COMPILER}")
                    endif()
                else()
                    # 如果 readlink 失败，直接检查路径字符串
                    string(FIND "${ENV_CXX}" "ccache" CCACHE_FOUND)
                    if(CCACHE_FOUND EQUAL -1)
                        set(GCC_CXX_COMPILER "${ENV_CXX}")
                        message(STATUS "[ClangConfig] 从环境变量 CXX 获取 C++ 编译器: ${GCC_CXX_COMPILER}")
                    endif()
                endif()
            endif()
        endif()
        
        # 如果环境变量只提供了其中一个编译器，尝试从另一个推导
        if(GCC_C_COMPILER AND NOT GCC_CXX_COMPILER)
            # 从 C 编译器路径推导 C++ 编译器路径
            get_filename_component(COMPILER_DIR "${GCC_C_COMPILER}" DIRECTORY)
            get_filename_component(COMPILER_NAME "${GCC_C_COMPILER}" NAME)
            string(REPLACE "gcc" "g++" CXX_COMPILER_NAME "${COMPILER_NAME}")
            set(CXX_COMPILER_PATH "${COMPILER_DIR}/${CXX_COMPILER_NAME}")
            if(EXISTS "${CXX_COMPILER_PATH}")
                get_filename_component(REAL_CXX_PATH "${CXX_COMPILER_PATH}" REALPATH)
                string(FIND "${REAL_CXX_PATH}" "ccache" CCACHE_FOUND)
                if(CCACHE_FOUND EQUAL -1)
                    set(GCC_CXX_COMPILER "${CXX_COMPILER_PATH}")
                endif()
            endif()
        elseif(GCC_CXX_COMPILER AND NOT GCC_C_COMPILER)
            # 从 C++ 编译器路径推导 C 编译器路径
            get_filename_component(COMPILER_DIR "${GCC_CXX_COMPILER}" DIRECTORY)
            get_filename_component(COMPILER_NAME "${GCC_CXX_COMPILER}" NAME)
            string(REPLACE "g++" "gcc" C_COMPILER_NAME "${COMPILER_NAME}")
            set(C_COMPILER_PATH "${COMPILER_DIR}/${C_COMPILER_NAME}")
            if(EXISTS "${C_COMPILER_PATH}")
                get_filename_component(REAL_C_PATH "${C_COMPILER_PATH}" REALPATH)
                string(FIND "${REAL_C_PATH}" "ccache" CCACHE_FOUND)
                if(CCACHE_FOUND EQUAL -1)
                    set(GCC_C_COMPILER "${C_COMPILER_PATH}")
                endif()
            endif()
        endif()
        
        # 方法1：如果环境变量未提供，直接检查标准路径中的文件（允许符号链接，但验证最终路径）
        if(NOT GCC_C_COMPILER)
            foreach(COMPILER_NAME gcc-11 gcc-10 gcc-9 gcc-8 gcc)
                foreach(COMPILER_PATH /usr/bin/${COMPILER_NAME} /usr/local/bin/${COMPILER_NAME} /bin/${COMPILER_NAME})
                    if(EXISTS "${COMPILER_PATH}")
                        # 解析符号链接，获取真实路径
                        get_filename_component(REAL_PATH "${COMPILER_PATH}" REALPATH)
                        # 验证最终路径不是 ccache
                        string(FIND "${REAL_PATH}" "ccache" CCACHE_FOUND)
                        if(CCACHE_FOUND EQUAL -1)
                            set(GCC_C_COMPILER "${COMPILER_PATH}")
                            message(STATUS "[ClangConfig] 在标准路径找到 GCC C 编译器: ${GCC_C_COMPILER} -> ${REAL_PATH}")
                            break()
                        else()
                            message(STATUS "[ClangConfig] 跳过 ccache 包装器: ${COMPILER_PATH} -> ${REAL_PATH}")
                        endif()
                    endif()
                endforeach()
                if(GCC_C_COMPILER)
                    break()
                endif()
            endforeach()
        endif()
        
        # 方法2：如果方法1没找到，使用 find_program 在标准路径中搜索
        if(NOT GCC_C_COMPILER)
            find_program(GCC_C_COMPILER 
                NAMES gcc-11 gcc-10 gcc-9 gcc-8 gcc
                PATHS /usr/bin /usr/local/bin /opt/local/bin /bin
                NO_DEFAULT_PATH
            )
            if(GCC_C_COMPILER)
                message(STATUS "[ClangConfig] 通过 find_program 在标准路径找到 GCC C 编译器: ${GCC_C_COMPILER}")
            endif()
        endif()
        
        # 方法3：如果方法2也没找到，使用 find_program 在整个 PATH 中搜索（不限制路径）
        if(NOT GCC_C_COMPILER)
            find_program(GCC_C_COMPILER 
                NAMES gcc-11 gcc-10 gcc-9 gcc-8 gcc
            )
            if(GCC_C_COMPILER)
                message(STATUS "[ClangConfig] 通过 find_program 在 PATH 中找到 GCC C 编译器: ${GCC_C_COMPILER}")
            endif()
        endif()
        
        # 如果找到了 C 编译器但还没有 C++ 编译器，查找 C++ 编译器
        if(GCC_C_COMPILER AND NOT GCC_CXX_COMPILER)
            # 从 C 编译器路径推导 C++ 编译器路径
            get_filename_component(COMPILER_DIR "${GCC_C_COMPILER}" DIRECTORY)
            get_filename_component(COMPILER_NAME "${GCC_C_COMPILER}" NAME)
            string(REPLACE "gcc" "g++" CXX_COMPILER_NAME "${COMPILER_NAME}")
            set(CXX_COMPILER_PATH "${COMPILER_DIR}/${CXX_COMPILER_NAME}")
            
            if(EXISTS "${CXX_COMPILER_PATH}")
                # 检查是否是符号链接指向 ccache
                get_filename_component(REAL_CXX_PATH "${CXX_COMPILER_PATH}" REALPATH)
                string(FIND "${REAL_CXX_PATH}" "ccache" CCACHE_FOUND)
                if(CCACHE_FOUND EQUAL -1)
                    set(GCC_CXX_COMPILER "${CXX_COMPILER_PATH}")
                endif()
            endif()
            
            # 如果没找到，使用 find_program 在标准路径中搜索
            if(NOT GCC_CXX_COMPILER)
                find_program(GCC_CXX_COMPILER 
                    NAMES g++-11 g++-10 g++-9 g++-8 g++
                    PATHS /usr/bin /usr/local/bin /opt/local/bin /bin
                    NO_DEFAULT_PATH
                )
                if(GCC_CXX_COMPILER)
                    message(STATUS "[ClangConfig] 通过 find_program 在标准路径找到 GCC C++ 编译器: ${GCC_CXX_COMPILER}")
                endif()
            endif()
            
            # 如果还是没找到，在整个 PATH 中搜索
            if(NOT GCC_CXX_COMPILER)
                find_program(GCC_CXX_COMPILER 
                    NAMES g++-11 g++-10 g++-9 g++-8 g++
                )
                if(GCC_CXX_COMPILER)
                    message(STATUS "[ClangConfig] 通过 find_program 在 PATH 中找到 GCC C++ 编译器: ${GCC_CXX_COMPILER}")
                endif()
            endif()
        endif()
        
        # 🔥 关键：验证找到的编译器路径，确保不是 ccache 包装器
        if(GCC_C_COMPILER)
            # 解析符号链接，获取真实路径
            execute_process(
                COMMAND readlink -f "${GCC_C_COMPILER}"
                OUTPUT_VARIABLE REAL_GCC_PATH
                OUTPUT_STRIP_TRAILING_WHITESPACE
                ERROR_QUIET
            )
            if(REAL_GCC_PATH)
                string(FIND "${REAL_GCC_PATH}" "ccache" CCACHE_FOUND)
                if(NOT CCACHE_FOUND EQUAL -1)
                    message(WARNING "⚠️  检测到 GCC 路径指向 ccache: ${GCC_C_COMPILER} -> ${REAL_GCC_PATH}")
                    message(WARNING "   正在查找真实编译器...")
                    set(GCC_C_COMPILER "")
                    set(GCC_CXX_COMPILER "")
                endif()
            else()
                # 如果 readlink 失败，直接检查路径字符串
                string(FIND "${GCC_C_COMPILER}" "ccache" CCACHE_FOUND)
                if(NOT CCACHE_FOUND EQUAL -1)
                    message(WARNING "⚠️  检测到 GCC 路径包含 ccache: ${GCC_C_COMPILER}")
                    message(WARNING "   正在查找真实编译器...")
                    set(GCC_C_COMPILER "")
                    set(GCC_CXX_COMPILER "")
                endif()
            endif()
        endif()
        
        # 如果找到了 GCC，显式设置编译器（必须在 project() 之前）
        if(GCC_C_COMPILER AND GCC_CXX_COMPILER)
            # 🔥 最终验证，确保不是 ccache 包装器
            execute_process(
                COMMAND readlink -f "${GCC_C_COMPILER}"
                OUTPUT_VARIABLE FINAL_REAL_GCC_PATH
                OUTPUT_STRIP_TRAILING_WHITESPACE
                ERROR_QUIET
            )
            if(FINAL_REAL_GCC_PATH)
                string(FIND "${FINAL_REAL_GCC_PATH}" "ccache" CCACHE_FOUND)
                if(NOT CCACHE_FOUND EQUAL -1)
                    message(FATAL_ERROR "❌ 检测到 GCC 路径指向 ccache: ${GCC_C_COMPILER} -> ${FINAL_REAL_GCC_PATH}\n"
                        "   请检查 /usr/bin/gcc 是否是符号链接指向 ccache\n"
                        "   检查方法: ls -la /usr/bin/gcc\n"
                        "   如果是符号链接，请删除并重新创建指向真实 gcc 的链接")
                endif()
            endif()
            # 使用 FORCE 确保即使缓存中已有 Clang，也使用 GCC
            # 同时设置初始值，防止 cmake 在 project() 时重新检测
            set(CMAKE_C_COMPILER "${GCC_C_COMPILER}" CACHE FILEPATH "C compiler" FORCE)
            set(CMAKE_CXX_COMPILER "${GCC_CXX_COMPILER}" CACHE FILEPATH "C++ compiler" FORCE)
            message(STATUS "✅ 已选择 GCC 编译器（USE_CLANG=0）")
            message(STATUS "   C 编译器: ${GCC_C_COMPILER}")
            message(STATUS "   C++ 编译器: ${GCC_CXX_COMPILER}")
        else()
            # 提供详细的诊断信息
            message(STATUS "[ClangConfig] 诊断信息：")
            message(STATUS "   GCC_C_COMPILER = ${GCC_C_COMPILER}")
            message(STATUS "   GCC_CXX_COMPILER = ${GCC_CXX_COMPILER}")
            
            # 检查常见路径
            message(STATUS "   检查常见路径：")
            foreach(COMPILER_NAME gcc gcc-11 gcc-10 gcc-9 gcc-8)
                foreach(COMPILER_PATH /usr/bin/${COMPILER_NAME} /usr/local/bin/${COMPILER_NAME} /bin/${COMPILER_NAME})
                    if(EXISTS "${COMPILER_PATH}")
                        get_filename_component(REAL_PATH "${COMPILER_PATH}" REALPATH)
                        message(STATUS "     ${COMPILER_PATH} -> ${REAL_PATH}")
                    endif()
                endforeach()
            endforeach()
            
            # 尝试使用 which 命令查找
            execute_process(
                COMMAND which gcc
                OUTPUT_VARIABLE WHICH_GCC
                OUTPUT_STRIP_TRAILING_WHITESPACE
                ERROR_QUIET
            )
            if(WHICH_GCC)
                message(STATUS "   which gcc: ${WHICH_GCC}")
            else()
                message(STATUS "   which gcc: 未找到")
            endif()
            
            execute_process(
                COMMAND which g++
                OUTPUT_VARIABLE WHICH_GXX
                OUTPUT_STRIP_TRAILING_WHITESPACE
                ERROR_QUIET
            )
            if(WHICH_GXX)
                message(STATUS "   which g++: ${WHICH_GXX}")
            else()
                message(STATUS "   which g++: 未找到")
            endif()
            
            message(FATAL_ERROR "❌ USE_CLANG=0 但未找到 GCC 编译器！\n"
                "   请安装 GCC: sudo apt-get install gcc g++\n"
                "   或检查 GCC 是否在 /usr/bin 或 /usr/local/bin 中\n"
                "   注意：不能使用 ccache 包装器路径\n"
                "   检查方法: ls -la /usr/bin/gcc\n"
                "   如果 GCC 已安装但检测失败，请检查上述诊断信息")
        endif()
    endif()
endif()

